package annotation;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.ElementFilter;
import javax.tools.Diagnostic;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Set;

@SupportedAnnotationTypes("MyData")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class MyDataProcessor extends AbstractProcessor {
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        for (TypeElement annotation : annotations) {
            for (TypeElement element : ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(annotation))) {
                try (PrintWriter writer = (PrintWriter) processingEnv.getFiler().createSourceFile(element.getQualifiedName() + "Builder").openWriter()) {
                    writer.println("public class " + element.getSimpleName() + "Builder {");
                    for (VariableElement field : ElementFilter.fieldsIn(element.getEnclosedElements())) {
                        String fieldName = field.getSimpleName().toString();
                        writer.println("    private " + field.asType() + " " + fieldName + ";");
                        writer.println("    public " + element.getSimpleName() + "Builder " +
                                fieldName + "(" + field.asType() + " " + fieldName + ") {");
                        writer.println("        this." + fieldName + " = " + fieldName + ";");
                        writer.println("        return this;");
                        writer.println("    }");
                    }
                    writer.println("    public " + element.getSimpleName() + " build() {");
                    writer.println("        return new " + element.getSimpleName() + "(this);");
                    writer.println("    }");
                    writer.println("}");
                } catch (IOException e) {
                    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.toString());
                }
            }
        }
        return true;
    }
}
